home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.1 / Amiga Developer CD v1.1 - May 1996 (1996)(Schatztruhe)[!].iso / Contributions / IAM / Networking / Envoy-2.0 / obs / Valuable_Concepts < prev    next >
Text File  |  1994-12-22  |  25KB  |  554 lines

  1. /*------------------------------------------------------------------------*/
  2. /*                                                                        *
  3.  *  $Id: Valuable_Concepts 1.1 1994/11/29 13:36:31 heinz Exp $
  4.  *                                                                        */
  5. /*------------------------------------------------------------------------*/
  6.  
  7. nipc.library
  8. ============
  9.  
  10. NIPC is a new library designed to provide a high level interface to
  11. networking hardware.  By using NIPC, programmers will not have to deal
  12. with all of the issues involved in networked communications such as
  13. sequencing, reliability, etc. NIPC has also been designed to be both
  14. easy to use and yet very powerful.
  15.  
  16. The NIPC API was designed in such a way that it would seem familiar to
  17. Amiga programmers that are familiar with Exec Messages and Device I/O.
  18. Many NIPC function calls such as GetTransaction(), DoTransaction() and
  19. ReplyTransaction() strongly resemble function calls already present in
  20. the Amiga OS.
  21.  
  22. At the lowest level, NIPC uses standard SANA-II device drivers so that
  23. it is capable of running on virtually any networking hardware,
  24. including ARCNET, Ethernet and even serial ports via SLIP.
  25.  
  26. NIPC transfers data between machines with primarily two concepts -
  27. "Entities" and "Transactions".
  28.  
  29.  
  30. Entities and Transactions
  31. =========================
  32.  
  33. An Entity is nothing more than a communications "endpoint". Any data
  34. sent using NIPC is sent between two of these endpoints - between two
  35. Entities.  An Entity is known by two characteristics: it's name (an
  36. ASCII string of up to 63 characters plus a terminating NULL), and the
  37. name of the machine on which it resides.   These Entities are
  38. guaranteed uniqueness by the fact that NIPC does not allow two
  39. Entities to exist on the same machine with the same name.
  40.  
  41. A given machine can have an unlimited number of Entities, each
  42. communicating with an unlimited number of other Entities. NIPC allows
  43. communication between Entities by establishing communications "paths"
  44. between individual Entities.  These paths are considered
  45. unidirectional in the sense that only the Entity that created the
  46. communications path can initiate a data transfer.  However, the
  47. "paths" are also bidirectional in the sense that data can flow in both
  48. directions.  In the diagram below, four Entities named 'A', 'B', 'C'
  49. and 'D' exist with various lines connecting the Entities together.
  50. Each of the lines indicates one of these data paths.  In the case
  51. below, Entity A has a path to Entity C and also has a path to B.  B
  52. has a path to D and also a path back to A.
  53.  
  54.  
  55.          -                         -
  56.         |A|   ---------------->   |B|
  57.          -    <----------------    -
  58.          |                         |
  59.          |                         |
  60.          |                         |
  61.          |                         |
  62.          V                         V
  63.          -                         -
  64.         |C|                       |D|
  65.          -                         -
  66.  
  67. A data path is created by one Entity attempting to locate, or 'find'
  68. another Entity.  This is done with the library function FindEntity().
  69. Conversely, a data path is removed by the library function
  70. LoseEntity().  These data paths exist only as long as the creator of
  71. the path wishes it to exist (or until one side of the path disappears
  72. for some reason).
  73.  
  74. Data is transferred from one point to another in Transactions. A
  75. Transaction is defined by a structure called the Transaction
  76. structure.  These are allocated and freed by the library functions
  77. AllocTransaction() and FreeTransaction().
  78.  
  79. A Transaction is always initiated by a program that has previously
  80. created a data path using the FindEntity() function. The transaction
  81. is then sent to a destination Entity, which deals with it however it
  82. wishes. The transaction is then returned to the sender.  As said
  83. before, these data paths are somewhat unidirectional.  In the above
  84. diagram, Entity A is allowed to send a Transaction to Entity C - who
  85. will receive it and send it back.  However, since Entity C has no data
  86. path to Entity A - it cannot initiate a Transaction.  However, both
  87. Entity A and Entity B established seperate data paths to each other
  88. allowing either to initiate a Transaction to the other.
  89.  
  90. A Transaction does allow for bidirectional data flow, however. The
  91. sender of a Transaction can attach "Request data" to it that the
  92. receiver can read.  The receiver is allowed to place data into a
  93. "Response buffer" and return that data back to the sender.
  94.  
  95. A Transaction can at any time be in one of three phases: the Request
  96. phase, the Servicing phase, and the Response phase.
  97.  
  98. The following diagrams may be useful in understanding each of these
  99. phases.  In the diagram below, one machine is about to communicate
  100. with another machine.  A program on machine 1 has succeeded at a
  101. FindEntity(), thereby locating and connecting to Entity B on Machine
  102. 2.  Now that the program has found Entity B, it attempts to begin a
  103. Transaction by using either BeginTransaction() or DoTransaction().
  104. Once the program has Begin/DoTransaction()'d, NIPC transmits the
  105. Request data portion of the Transaction to Machine 2.  This phase of
  106. the Transaction is the Request phase, and is shown in Diagram 1.
  107.  
  108. When the Transaction is received by NIPC on Machine 2, it is placed
  109. onto the destination Entity - Entity B in this example. While it
  110. remains on this Entity, the Transaction remains in the Request phase.
  111. Once the server program on Machine 2 attempts a GetTransaction() on
  112. that Entity and removes the given Transaction from the Entity, the
  113. Transaction enters the Servicing phase. This is shown in Diagram 2.
  114.  
  115. While the server program attempts to fufill the needs of the
  116. Transaction the Transaction remains in the Servicing phase.  When
  117. the server program has finished with the Transaction and attempts
  118. to return it to Machine 1 by calling ReplyTransaction(), the
  119. Transaction enters the Response phase.  The response data is
  120. transmitted back to the original sender (Machine 1) and the
  121. Transaction is returned to the source Entity (Entity A) as shown
  122. in Diagram 3.  The Transaction remains in this phase forever - or
  123. until it is reused.  The trans_Type field indicates which phase a
  124. given Transaction is in.
  125.  
  126.  
  127.      MACHINE 1                            MACHINE 2
  128.       ______                               ______
  129.      |Entity|        Request Data         |Entity|
  130.      |  A   |        ------------->       |  B   |
  131.      |______|                             |______|
  132.                     Request Phase
  133.                       Diagram 1.
  134.  
  135.  
  136.      MACHINE 1                            MACHINE 2
  137.       ______                               ______
  138.      |Entity|                             |Entity| (Server has
  139.      |  A   |                             |  B   |  Transaction)
  140.      |______|                             |______|
  141.                     Servicing Phase
  142.                       Diagram 2.
  143.  
  144.  
  145.      MACHINE 1                            MACHINE 2
  146.       ______                               ______
  147.      |Entity|       Response Data         |Entity|
  148.      |  A   |        <------------        |  B   |
  149.      |______|                             |______|
  150.                     Response Phase
  151.                       Diagram 3.
  152.  
  153.  
  154.  
  155.  
  156.  
  157. Analogies and Similarities
  158. ==========================
  159.  
  160. NIPC shares many concepts with Exec messages and device I/O.  One such
  161. concept is the idea that applications communicate with other
  162. applications or devices by sending and receiving finite pieces of
  163. data, usually in the form of an Exec Message. NIPC also shares the
  164. concept of a communications endpoint similar to the Exec Message Port.
  165.  
  166. In NIPC, the communications endpoint is known as an Entity. Entities
  167. are used as both the source and destinations of data being sent
  168. between two applications.  The data being sent between applications is
  169. known in NIPC as a Transaction.
  170.  
  171. Shown below are two diagrams that illustrate how Messages and Ports
  172. relate to Transactions and Entities.
  173.  
  174.  
  175. Application<-->MsgPort<----Message----->MsgPort<-->Application
  176.  
  177. Application<-->Entity<---Transactions--->Entity<-->Application
  178.  
  179.  
  180. Unfortunately, it gets more complicated than the above diagram can
  181. show.  Unlike Exec Messages, NIPC Transactions are not guaranteed to
  182. arrive at a destination Entity in a preset amount of time.  In fact,
  183. it is possible that a Transaction will never make it to it's
  184. destination due to machine and/or network failures.  NIPC does make a
  185. good effort at delivering transactions, however.  The lower level
  186. protocols used in NIPC help to provide this functionality.
  187.  
  188. Another difference between NIPC communications and Exec Messages is
  189. that NIPC is designed around a client-server model. In many cases the
  190. two applications communicating will be a client and a server, such as
  191. the case with a print spooler or a network filesystem.  Because of
  192. this, clients have more control over the transactions than the servers
  193. do.  This will become apparent later on.
  194.  
  195.  
  196. Using NIPC
  197. ==========
  198.  
  199. Before communication via NIPC can begin, each application that will be
  200. involved must create an Entity.  This is done by calling
  201. CreateEntity().  Once an application has created it's own entity, it
  202. must find the other application's entity.  Typically, the entity to be
  203. found is a public Entity created by a server.
  204.  
  205. To find an Entity created by another program, you call FindEntity().
  206. FindEntity() has parameters that allow you to specify the name of the
  207. Entity, the name of the host that you are trying to find the Entity
  208. on, and the Entity that you will be using for the source of your
  209. Transactions.
  210.  
  211. The reason that FindEntity() also requires a pointer to your program's
  212. Entity is that NIPC communication is connection oriented.  This means
  213. that a connection forms between your Entity and the Entity you found.
  214. This connection will continue to exist until you no longer need it or
  215. until a permanent network failure or machine failure occurs.  When you
  216. are done communicating with the other Entity, you call LoseEntity().
  217. The concept of a connection does not exist with Exec Messages.  This
  218. is why you must use a Forbid()/Permit() pair when communicating with
  219. public message ports to guarantee that the port does not go away in
  220. between the time you call FindPort() and PutMsg().
  221.  
  222. Once you have created your entity and found the remote entity, you
  223. must allocate a Transaction structure.  The only supported way of
  224. doing this is to call the NIPC function AllocTransaction().
  225.  
  226. AllocTransaction() allows you to optionally specify buffer sizes for
  227. any data being sent and/or any data that may be received that the
  228. Transaction is complete.  You may also allocate your own buffers, but
  229. you are responsible for freeing them yourself.
  230.  
  231. A Transaction is sent on it's way by calling either BeginTransaction()
  232. or DoTransaction().  BeginTransaction() will return immediately unless
  233. you are trying to send more data than the network protocols are
  234. capable of handling at the moment. Once your Transaction has begun,
  235. BeginTransaction() will return. It should be noted that the amount of
  236. time that BeginTransaction() will block will usually be quite small.
  237. Therefore, BeginTransaction() should be considered an asynchronous
  238. call.
  239.  
  240. DoTransaction() will block until either the Transaction has completed
  241. or an error occured.  Because your program will not be able to
  242. anything until DoTransaction() returns, it is strongly suggested that
  243. you try to avoid it, or spawn a separate task or process to call
  244. DoTransaction().
  245.  
  246. When the Transaction returns, you should examine it to determine how
  247. much, if any, data was returned and whether or not an error condition
  248. occured.
  249.  
  250. Programs acting as servers usually do not call AllocTransaction(),
  251. BeginTransaction() or DoTransaction(). Typically, a server will wait
  252. for a Transaction to arrive at it's public Enitity.  This may be done
  253. by using either WaitEntity() or by using the Exec Wait() function.  To
  254. see if a Transaction is available at your Entity, you should call
  255. GetTransaction() which will eithe return a pointer to a Transaction or
  256. NULL if there are not more transactions to be processd.
  257.  
  258. For each transaction you receive, you should examine it to determine
  259. what you should do with the data in it, or if you need to return some
  260. data to a client.  Once you have finished processing the transaction,
  261. you must return it to it's sender by calling ReplyTransaction().
  262.  
  263. For an example NIPC client and server, please see the two files named
  264. RemoteRequest.c and RequestServer.c.  These two programs allow you to
  265. put up a requester on a remote machine running NIPC.
  266.  
  267.  
  268. Structure and Function call Overview
  269. ====================================
  270.  
  271. While the text below will give you a useful introducation into what is
  272. needed to use nipc.library, you should in any case refer to the
  273. autodocs and include files for nipc.library to get the complete
  274. picture. Only the most important things are outlined here and some
  275. stuff is omitted.
  276.  
  277. struct Transaction
  278. {
  279.         struct Message trans_Msg;
  280.         struct Entity *trans_SourceEntity;
  281.         struct Entity *trans_DestinationEntity;
  282.         UBYTE          trans_Command;
  283.         UBYTE          trans_Type;
  284.         ULONG          trans_Error;
  285.         ULONG          trans_Flags;
  286.         ULONG          trans_Sequence;
  287.         APTR           trans_RequestData;
  288.         ULONG          trans_ReqDataLength;
  289.         ULONG          trans_ReqDataActual;
  290.         APTR           trans_ResponseData;
  291.         ULONG          trans_RespDataLength;
  292.         ULONG          trans_RespDataActual;
  293.         UWORD          trans_Timeout;
  294. };
  295.  
  296.  
  297.     trans_Msg
  298.  
  299.         Used internally by nipc.library.  Do not use or examine.
  300.  
  301.     trans_SourceEntity
  302.  
  303.         This is the entity from which the Transaction originated.
  304.         This is filled in by Begin/DoTransaction().  It may be
  305.         examined by the responder.  The common use of this field is
  306.         for a responder who has just received a Transaction from
  307.         another Entity to pass into GetHostName() or GetEntityName() -
  308.         to determine the name of the Entity that sent the Transaction,
  309.         and the name of the machine from which that Transaction
  310.         originiated. Note that this must be done before replying the
  311.         Transaction. The responder must not cache the value.
  312.  
  313.     trans_DestinationEntity
  314.  
  315.         Used internally by nipc.library.  Do not use or examine.
  316.  
  317.     trans_Command
  318.  
  319.         This field is filled in by the originator of the Transaction
  320.         and may be examined by the responder.  It is generally only
  321.         read by the responder.  This field is generally used to
  322.         indicate the particular action the originator desires the
  323.         responder to perform.  It is analogous to the IORequest
  324.         io_Command field. Note that, unlike with Exec Device I/O,
  325.         there are no standard responder commands which all requesters
  326.         can expect all responders to understand.
  327.  
  328.     trans_Type
  329.  
  330.         One of TYPE_REQUEST, TYPE_RESPONSE or TYPE_SERVICING.  A
  331.         Transaction is always in one of three phases - the Request
  332.         phase, between the time it is Begin/DoTransaction()'d and the
  333.         time the server GetTransaction()'s it from it's destination
  334.         Entity; the Servicing phase, between GetTransaction()'ing it,
  335.         and ReplyTransaction()'ing it; and lastly the Response phase,
  336.         which begins when the Transaction is returned to it's Source
  337.         Entity. The most common use of this field is to determine if a
  338.         Transaction obtained from GetTransaction() is a Request from
  339.         another Entity, or merely a returning Transaction that was
  340.         originally sent from this Entity.
  341.  
  342.     trans_Error
  343.  
  344.         Both nipc.library and the user may write and examine this
  345.         field. It is cleared (set to ENVOYERR_NOERROR) on a call to
  346.         Do/BeginTransaction().  If the Transaction can be successfully
  347.         copied locally or over the network, any value placed in this
  348.         field by the responder will be here.  If the Transaction
  349.         cannot be copied for some reason, nipc.library will place it's
  350.         error code here.  Common error codes are defined in
  351.         <envoy/errors.h>. Human-understandable text errors can be
  352.         obtained from these error numbers with a call to envoy.library
  353.         [NOT YET AVAILABLE].
  354.  
  355.     trans_Flags
  356.  
  357.         This field is a series of nipc.library flags.  These flags
  358.         indicate several things, including who is responsible for
  359.         freeing buffers.  Flags should not be set or cleared by the
  360.         user except through NIPC functions or as permitted by comments
  361.         in the Includes.
  362.  
  363.     trans_Sequence
  364.  
  365.         Used internally by nipc.library.  Do not use or examine.
  366.  
  367.     trans_RequestData
  368.  
  369.         Pointer to any data needed from the requester by the
  370.         responder. This may be NULL if trans_ReqDataActual is zero,
  371.         indicating that no request data was necessary.  The responder
  372.         should make no changes to data in this buffer!  Programs which
  373.         do will behave differently in networked vs. local
  374.         Transactions. See the GetTransaction() autodoc for more
  375.         details.
  376.  
  377.     trans_ReqDataLength
  378.  
  379.         Length of the buffer pointed to by trans_RequestData.  It is
  380.         eventually used by the allocator of the buffer to free the
  381.         buffer.
  382.  
  383.     trans_ReqDataActual
  384.  
  385.         Length of data in the buffer pointed to by trans_RequestData
  386.         which will actually be used by the responder.  This allows
  387.         re-used Transaction structures to have large buffers which
  388.         aren't copied across the network if the whole buffer isn't
  389.         filled with data.  This may be NULL if no data is to be sent
  390.         to the responder.
  391.  
  392.     trans_ResponseData
  393.  
  394.         Pointer to a buffer into which any reply will be placed by the
  395.         responder.  This may be NULL if trans_RespDataLength is NULL.
  396.         Currently this must be allocated by the requester, either at
  397.         AllocTransaction() time or subsequently prior to
  398.         Do/BeginTransaction().
  399.  
  400.     trans_RespDataLength
  401.  
  402.         Length of the buffer pointed to by trans_ResponseData.  It is
  403.         eventually used by the allocator of the buffer to free the
  404.         buffer.  The allocator of the buffer is never the responder.
  405.  
  406.     trans_RespDataActual
  407.  
  408.         Length of the data in the buffer pointed to by
  409.         trans_ResponseData actually placed there by the responder.
  410.         This allows the responder to specify that the information it
  411.         is returning is smaller than the buffer provided in order to
  412.         avoid unnecessary copying unused buffer across the network.
  413.  
  414.     trans_Timeout
  415.  
  416.         This is the value in seconds that the requester expects as the
  417.         maximum time for the responder to spend processing the
  418.         request. nipc.library will add to this value the maximum time
  419.         it expects the transfer of data between the Entities to take
  420.         (this is variable depending on the distance of the machines
  421.         communicating).  If a Transaction exceeds the total timeout
  422.         and NIPC can abort the Transaction, it will be returned to the
  423.         requester with trans_Error set to ENVOYERR_TIMEOUT.  Though no
  424.         timeout will be used if trans_Timeout is set to zero, most
  425.         Transactions should have a timeout.  If there is no timeout, a
  426.         Transaction received by the responder but not replied (i.e.,
  427.         because the machine crashed before getting to the reply) would
  428.         never be returned (unless the requester called
  429.         AbortTransaction()).  Thus, all programs should specify a
  430.         Timeout other than zero or eventually call AbortTransaction()
  431.         themselves.
  432.  
  433.         On the requester's side, Transactions are moved around with
  434.         nipc.library functions which look and act much like Exec
  435.         Device I/O functions.  Instead of DoIO(), WaitIO(), CheckIO(),
  436.         AbortIO() and BeginIO(), nipc.library has DoTransaction(),
  437.         WaitTransaction(), CheckTransaction(), AbortTransaction() and
  438.         BeginTransaction().
  439.  
  440.     DoTransaction(dest_entity, src_entity, transaction)
  441.  
  442.         an easy-to-use Transaction function.  It initiates a
  443.         Transaction and waits for its completion.  This is a
  444.         synchronous function; it does not return until completion of
  445.         the Transaction.  If the Transaction never completes, this
  446.         call never returns. Non-trivial programs should avoid the use
  447.         of this function in order to continue processing break signals
  448.         or other user input. Use BeginTransaction() and Wait() on the
  449.         Entity's signal bit instead.
  450.  
  451.     BeginTransaction(dest_entity, src_entity, transaction)
  452.  
  453.         initiates a Transaction without waiting for completion.  This
  454.         is an asynchronous Transaction; control returns immediately.
  455.         Use GetTransaction() on src_entity to get the replied
  456.         Transaction.
  457.  
  458.     transaction = GetTransaction(entity)
  459.  
  460.         Gets replied Transactions off of your source Entity.  You
  461.         should use Wait() or WaitTransaction() rather than
  462.         continuously polling. Once woken up from a
  463.         Wait[Transaction](), you should loop on GetTransaction() while
  464.         it returns something other than NULL to get all Transactions
  465.         off the Entity.
  466.  
  467.     WaitTransaction(transaction)
  468.  
  469.         Waits for the completion of a previously initiated
  470.         asynchronous Transaction.  This function will not return
  471.         control until the Transaction has completed (successfully or
  472.         unsuccessfully). Programs should not WaitTransaction() on a
  473.         Transaction that has not actually been sent.
  474.  
  475.     status = CheckTransaction(transaction)
  476.  
  477.         Examines a previously queued Transaction, and returns
  478.         information on whether it has completed or not.
  479.  
  480.     AbortTransaction(transaction)
  481.  
  482.         attempts to cancel a Transaction.  AbortTransaction() may
  483.         fail; if it succeeds, the Transaction is replied by NIPC
  484.         earlier than it may otherwise have been replied. Programs must
  485.         wait for the reply before actually reusing the Transaction.
  486.         AbortTransaction() takes no action on Transactions which are
  487.         already completed.
  488.  
  489.         The responder's side of a Transaction uses functions which are
  490.         similar to those that manipulate Exec Ports and Messages.
  491.         Rather than WaitPort(), GetMsg() and ReplyMsg(), there are
  492.         WaitEntity(), GetTransaction() and ReplyTransaction().
  493.  
  494.     WaitEntity(localentity)
  495.  
  496.         Waits for a Transaction to arrive at an Entity.  Non-trivial
  497.         programs should avoid using this function in order to continue
  498.         processing break signals or other user input.  Use Wait() on
  499.         the Entity's signal bit instead.
  500.  
  501.     transaction = GetTransaction(entity)
  502.  
  503.         Transactions must be removed from Entities on the responder's
  504.         side of a Transaction with a call to GetTransaction().
  505.  
  506.         Once a responder is done processing a Transaction, it must
  507.         return the Transaction to the requester using the
  508.         ReplyTransaction() function.
  509.  
  510.         Unlike Exec Ports which can be created manually or with an
  511.         amiga.lib function, Entities must be created and destroyed
  512.         with nipc.library or services.library functions.
  513.  
  514.     myentity = CreateEntity(tag1, ...)
  515.  
  516.         creates a new Entity which will can be used for calls to
  517.         WaitEntity() and GetTransaction().  Entities created with
  518.         CreateEntity() must eventually be deleted with DeleteEntity().
  519.  
  520.     DeleteEntity(entity)
  521.  
  522.         deletes an Entity created by CreateEntity().  Do not use on
  523.         Entities found with FindEntity() (see below).
  524.  
  525.         Although the Entity structure is not publicly defined, two
  526.         functions are provided to return some information about a given
  527.         Entity.
  528.  
  529.     success = GetHostName(entity, stringptr, available)
  530.  
  531.         provides the name of the host on which a given Entity was
  532.         created.  This is useful to responders that need to know which
  533.         machines they are responding to.
  534.  
  535.     success = GetEntityName(entity stringptr available)
  536.  
  537.         provides the name of the Entity.  This is primarily useful to
  538.         responders that need to know the name of the Entities to which
  539.         they are responding.
  540.  
  541.     remoteentity = FindEntity(host, entityname, src_entity, errptr)
  542.  
  543.         Finds an Entity created by CreateEntity().  This Entity may be
  544.         used as the destination of a Do/BeginTransaction().  Entities
  545.         found with FindEntity() must eventually be forgotten with a call
  546.         to LoseEntity().
  547.  
  548.     LoseEntity(entity)
  549.  
  550.         Forgets about an Entity found with a call to FindEntity().
  551.  
  552.  
  553.  
  554.